package halberd.filter;

import halberd.DataType;
import halberd.ImgFilter;
import halberd.data.ImgData;
import halberd.data.ImgDataFactory;
/**
 * 大津法二值化
 * @author jiang
 *
 */
public class OtsuFilter implements ImgFilter {

	public ImgData process(ImgData input) {
		if(!canProcess(input)) {
			return null;
		}
		ImgData result=ImgDataFactory.createImgData(input.getWidth(), input.getHeight());
		int[][][] ints=input.getDatas();
		otsu(ints,result.getDatas(),input.getWidth(),input.getHeight());
		result.setDataType(DataType.BINARY);
		return result;
	}
	private boolean canProcess(ImgData input) {
		if(input==null) {
			return false;
		}
		DataType dt=input.getDataType();
		if(dt==DataType.GRAY) {
			return true;
		}
		return false;
	}
	private void otsu(int[][][] src,int[][][] dst,int w,int h) {
		int[] hist=new int[256];
		for(int i=0;i<256;++i)
		{
			hist[i]=0;
		}
		for(int i=0;i<w;++i)
		{
			for(int j=0;j<h;++j)
			{
				hist[src[i][j][4]]++;
			}
		}
		int finded=128;
		double fangcha0=100000000;
		for(int i=1;i<255;++i)
		{
			double cls1=0;
			double count1=0;
			double cls2=0;
			double count2=0;
			for(int j=0;j<i;++j)
			{
				cls1+=hist[j]*(i-j);
				count1+=hist[j];
			}
			for(int j=i;j<256;++j)
			{
				cls2+=hist[j]*(j-i);
				count2+=hist[j];
			}
			count1=count1==0?0.000001:count1;
			count2=count2==0?0.000001:count2;
			double fangcha=Math.abs(cls1/count1-cls2/count2);
			if(fangcha<fangcha0)
			{
				finded=i;
				fangcha0=fangcha;
			}
		}//end for
		for(int i=0;i<w;++i)
		{
			for(int j=0;j<h;++j)
			{
				if(src[i][j][4]>finded)
				{
					dst[i][j][4]=255;
				}else
				{
					dst[i][j][4]=0;
				}
			}
		}
	}
}
